package generator;

import java.util.Random;

import core.course.Course;

/**
 * Generates a bank of courses (an instance of the scheduling problem).
 * 
 * @author omerlevy
 */
public class CourseBankGenerator {

	/**
	 * @param random The random generator to be used.
	 * @param numCourses The number of courses in the bank.
	 * @return A randomly generated course bank.
	 */
	public CourseBank generateCourseBank(Random random, int numCourses) {
		CourseBank bank = new CourseBank();
		
		for (int i = 0; i < numCourses; i++) {
			bank.addCourse(generateCourse(random));
		}
		
		generateAdjacencies(random, bank);
		
		return bank;
	}

	/**
	 * @param random The random generator to be used.
	 * @return A randomly generated course.
	 */
	private Course generateCourse(Random random) {
		Course course = new Course(
				random.nextInt(TIMESLOTS), random.nextInt(MAX_WORKLOAD) + 1);
		
		double variance = 100 / course.getWorkload();
		double expected = 100 - (variance / 2);
		double grade = 0;
		while (grade <= 0 || 100 < grade) {
			grade = random.nextGaussian() * variance + expected;			
		}
		course.setGrade((int) Math.round(grade));
		
		return course;
	}

	/**
	 * Generates adjacent courses for each course.
	 * @param random The random generator to be used.
	 * @param bank The course bank.
	 */
	private void generateAdjacencies(Random random, CourseBank bank) {
		int maxAdjacents = (int) Math.ceil(Math.sqrt(bank.getNumCourses()));
		for (int i = 0; i < bank.getNumCourses(); i++) {
			int adjacents = random.nextInt(maxAdjacents);
			for (int j = 0; j < adjacents; j++) {
				bank.getCourse(i).addAdjacentCourse(
						bank.getCourse(random.nextInt(bank.getNumCourses())));
			}
		}
	}
	
	
	/* --- Constants --- */
	
	/** The number of weekly time slots. */
	private static final int TIMESLOTS = 20;
	
	/** The maximum workload for any course. */
	private static final int MAX_WORKLOAD = 10;
	
}
